package io.sage.modules.hcnet.service.impl;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.nio.ByteBuffer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import io.sage.modules.camera.dao.BMonitorCameraMapper;
import io.sage.modules.camera.dao.BMonitorCamersHistoryMapper;
import io.sage.modules.camera.entity.BMonitorCamera;
import io.sage.modules.camera.entity.BMonitorCamersHistory;
import io.sage.modules.camera.entity.MonitorCameraInfo;
import io.sage.modules.oss.cloud.OSSFactory;
import io.sage.modules.sys.entity.SysUserEntity;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import com.sun.jna.NativeLong;

import io.sage.common.hcnet.HCNetSDK;
import io.sage.common.utils.DateUtils;
import io.sage.modules.hcnet.service.HcNetRadioService;
import io.sage.modules.rxtx.service.impl.RxtxServiceImpl;
import io.sage.modules.warn.entity.BRfidWarn;

/**
 * Created by Mafy on 2019/7/19.
 * 海康录像service
 */
@Service
public class HcNetRadioServiceImpl implements HcNetRadioService {

    private static Logger logger = LoggerFactory.getLogger(RxtxServiceImpl.class);

    NativeLong lUserID1 = null; //登录句柄

    NativeLong lPreviewHandle1 =null;//预览句柄

    NativeLong lUserID2 = null; //登录句柄

    NativeLong lPreviewHandle2 =null;//预览句柄

    HCNetSDK hCNetSDK = HCNetSDK.INSTANCE;

    boolean initSuc = hCNetSDK.NET_DVR_Init();//设备初始化

    @Value(value = "${camera.isInitCamera}")
    private boolean isInitCamera;
    @Value(value = "${camera.ip1}")
    private String ip1;
    @Value(value = "${camera.ip2}")
    private String ip2;
    @Value(value = "${camera.userName1}")
    private String userName1;
    @Value(value = "${camera.userName2}")
    private String userName2;
    @Value(value = "${camera.password1}")
    private String password1;
    @Value(value = "${camera.password2}")
    private String password2;
    @Value(value = "${camera.port1}")
    private int port1;
    @Value(value = "${camera.port2}")
    private int port2;
    @Value(value = "${camera.saveTime}")
    private int saveTime;
    @Value(value = "${web.hcvideo-path}")
    private String videoPath;
    @Value(value = "${camera.camera1Name}")
    private String camera1Name;
    @Value(value = "${camera.camera2Name}")
    private String camera2Name;

    @Autowired
    private BMonitorCameraMapper bMonitorCameraMapper;
    
    
    private List<BRfidWarn> bRfidWarns;

     Map<Integer,BMonitorCamera> mapCamera=new HashMap<>();
    
    @Autowired
    private BMonitorCamersHistoryMapper bMonitorCamersHistoryMapper;


    @Override
    public boolean hcNetPlay() {
        if(!isInitCamera){
            logger.info("海康设备初始化校验，当前拒绝初始化，修改请到配置文件修改isInitCamera为true");
            return false;
        }
        return hcNetPlay1() && hcNetPlay2();
    }
    @Override
    public Map<String,Object> catchPic(BMonitorCamera bMonitorCamera, SysUserEntity sysUserEntity) {
        Map<String,Object> map=new HashMap<>();
        map.put("flag", false);
        lUserID1=mapCamera.get(bMonitorCamera.getId()).getUserId();
        NativeLong chanLong = new NativeLong(1);
        //cameraInfo.setChannel(chanLong);

        // 返回Boolean值，判断是否获取设备能力
        HCNetSDK.NET_DVR_WORKSTATE_V30 devwork = new HCNetSDK.NET_DVR_WORKSTATE_V30();
        if (!hCNetSDK.NET_DVR_GetDVRWorkState_V30(lUserID1, devwork)) {
            System.out.println("返回设备状态失败");
        }

        //JPEG图像信息结构体
        HCNetSDK.NET_DVR_JPEGPARA jpeg = new HCNetSDK.NET_DVR_JPEGPARA();
        jpeg.wPicSize = 2;// 设置图片的分辨率
        jpeg.wPicQuality = 2;// 设置图片质量

        //设置图片大小
        IntByReference a = new IntByReference();

        //设置字节缓存
        ByteBuffer jpegBuffer = ByteBuffer.allocate(1024 * 1024);

        //抓图到文件
        //boolean is = sdk.NET_DVR_CaptureJPEGPicture(cameraInfo.getUserId(),cameraInfo.getChannel(),jpeg, fileNameString);
        byte[] bytes = null;
        boolean returnboll = false;

        HCNetSDK.NET_DVR_JPEGPARA jpeginfo = new HCNetSDK.NET_DVR_JPEGPARA();
        jpeginfo.wPicQuality = 2;
        jpeginfo.wPicSize = 0;
        int dwPicSize = 200 * 1024;
        IntByReference lpSizeReturned = new IntByReference();
        lpSizeReturned.setValue(0);
        NativeLong DVRChannel = new NativeLong();
        DVRChannel.setValue(1);
        Date date = new Date();
        DateFormat format = new SimpleDateFormat("yyyyMMddHHmm");
        Pointer p = new Memory(200 * 1024);
        returnboll = (boolean) hCNetSDK.NET_DVR_CaptureJPEGPicture_NEW(lUserID1, DVRChannel, jpeginfo, p, dwPicSize, lpSizeReturned);
        bytes = p.getByteArray(0, lpSizeReturned.getValue());
        String suffix=".png";
        String url = OSSFactory.build().uploadSuffix(bytes, suffix);
        BMonitorCamersHistory bMonitorCamersHistory=new BMonitorCamersHistory();
        bMonitorCamersHistory.setCameraId(bMonitorCamera.getId());
        date=new Date();

        bMonitorCamersHistory.setCreateTime(date);
        bMonitorCamersHistory.setCreateUser(sysUserEntity.getUserId().intValue());
        if(bMonitorCamera.getExpireDate()!=null){
            date=DateUtils.addDateDays(date, bMonitorCamera.getExpireDate());
            bMonitorCamersHistory.setExpireDate(date);
        }
        bMonitorCamersHistory.setUrl(url);
       int i= bMonitorCamersHistoryMapper.insert(bMonitorCamersHistory);

        map.put("flag", i>0?true:false);
        map.put("url", url);
        return map;
    }

    /**
     * 初始化所有摄像头
     * @return
     */
    @Override
    public boolean initAllPlay() {
        Map<String,Object> map=new HashMap<>();
        map.put("isDel", 0);
        map.put("isused", 1);
        List<BMonitorCamera>bMonitorCameras=this.bMonitorCameraMapper.selectBMonitorCameraList(map);
        if(!isInitCamera){
            logger.info("海康设备初始化校验，当前拒绝初始化，修改请到配置文件修改isInitCamera为true");
            return false;
        }
        //创建静态资源文件路径
        File file = new File(videoPath);
        if(!file.exists()){
            file.mkdirs();
        }
        if(!initSuc){
            logger.info("错误参数：{}",hCNetSDK.NET_DVR_GetLastError());
            return false;
        }

        for (BMonitorCamera bMonitorCamera:bMonitorCameras) {
            if(StringUtils.isEmpty(bMonitorCamera.getIp())||StringUtils.isEmpty(bMonitorCamera.getInnerPort())
                ||StringUtils.isEmpty(bMonitorCamera.getUsername())||StringUtils.isEmpty(bMonitorCamera.getPassword())){
                logger.info("摄像头"+bMonitorCamera.getIp()+"登录结果：失败");
                continue;
            }
            lUserID1 = hCNetSDK.NET_DVR_Login_V30(bMonitorCamera.getIp(), (short) Integer.parseInt(bMonitorCamera.getInnerPort()),bMonitorCamera.getUsername(),bMonitorCamera.getPassword(), null);//登陆
            logger.info("摄像头"+bMonitorCamera.getIp()+"登录结果：{}",lUserID1);
            bMonitorCamera.setUserId(lUserID1);
            if(lUserID1.intValue() < 0){
                logger.info("摄像头"+bMonitorCamera.getIp()+"登录结果：失败");
                continue;
            }
            mapCamera.put(bMonitorCamera.getId(), bMonitorCamera);
        }
        return true;
    }

    @Override
    public boolean hcNetPlay1() {

        //创建静态资源文件路径
        File file = new File(videoPath);
        if(!file.exists()){
            file.mkdirs();
        }
        if(!isInitCamera){
            logger.info("海康设备初始化校验，当前拒绝初始化，修改请到配置文件修改isInitCamera为true");
            return false;
        }

        logger.info("海康设备初始化initSuc:{}",initSuc);
        if(!initSuc){
            logger.info("错误参数：{}",hCNetSDK.NET_DVR_GetLastError());
            return false;
        }

        lUserID1 = hCNetSDK.NET_DVR_Login_V30(ip1, (short) port1,userName1,password1, null);//登陆
        logger.info("摄像头1登录结果：{}",lUserID1);
        if(lUserID1.intValue() < 0){
            return false;
        }

        HCNetSDK.NET_DVR_CLIENTINFO m_strClientInfo = new HCNetSDK.NET_DVR_CLIENTINFO();//预览参数 用户参数
        m_strClientInfo.lChannel = new NativeLong(1);

        lPreviewHandle1 = hCNetSDK.NET_DVR_RealPlay_V30(lUserID1, m_strClientInfo, null, null, true);//播放，窗口句柄在m_strClientInfo里
        logger.info("摄像头1播放句柄：{}",lPreviewHandle1);
        if(lPreviewHandle1.intValue() < 0){
            return false;
        }
        return true;
    }

    @Override
    public boolean hcNetPlay2() {

        if(!isInitCamera){
            logger.info("海康设备初始化校验，当前拒绝初始化，修改请到配置文件修改isInitCamera为true");
            return false;
        }
        logger.info("海康设备初始化initSuc:{}",initSuc);
        if(!initSuc){
            logger.info("错误参数：{}",hCNetSDK.NET_DVR_GetLastError());
            return false;
        }
        lUserID2 = hCNetSDK.NET_DVR_Login_V30(ip2, (short) port2,userName2,password2, null);//登陆
        logger.info("摄像头2登录结果：{}",lUserID2);
        if(lUserID2.intValue() < 0){
            logger.info("错误参数：{}",hCNetSDK.NET_DVR_GetLastError());
            System.out.println("error:"+hCNetSDK.NET_DVR_GetLastError());
            return false;
        }

        HCNetSDK.NET_DVR_CLIENTINFO m_strClientInfo = new HCNetSDK.NET_DVR_CLIENTINFO();//预览参数 用户参数
        m_strClientInfo.lChannel = new NativeLong(2);

        lPreviewHandle2 = hCNetSDK.NET_DVR_RealPlay_V30(lUserID2, m_strClientInfo, null, null, true);//播放，窗口句柄在m_strClientInfo里
        logger.info("摄像头2播放句柄：{}",lPreviewHandle2);
        if(lPreviewHandle2.intValue() < 0){
            logger.info("错误参数：{}",hCNetSDK.NET_DVR_GetLastError());
            return false;
        }
        return true;
    }

    
    /**
     * 设备1进行录制
     * bRfidWarns list中有异常数据id，需要在此处处理
     * @return
     */
    @Override
    public boolean hcNetSaveRadio1(List<BRfidWarn> bRfidWarns) {
        //该处进行录像功能
        if(!isInitCamera){
            logger.info("海康设备初始化校验，当前拒绝初始化，修改请到配置文件修改isInitCamera为true");
            return false;
        }
        
        this.bRfidWarns = bRfidWarns;
        String milliseconds = DateUtils.getTimeWithMilltsecond();
        String savepath = videoPath+camera1Name+milliseconds+".mp4";
        logger.info("文件保存路径：{}",savepath);
        hcNetSaveRadio2();
        return hcSaveFun(lPreviewHandle1,savepath);
    }

    /**
     * 设备2进行录制
     * @return
     */
    @Override
    public boolean hcNetSaveRadio2() {
        //该处进行录像功能
        String milliseconds = DateUtils.getTimeWithMilltsecond();
        return hcSaveFun(lPreviewHandle2,videoPath+camera2Name+milliseconds+".mp4");
    }

    private boolean hcSaveFun(NativeLong lPreviewHandle,String savePath){
        //该处进行录像功能
        if(!(hCNetSDK.NET_DVR_SaveRealData(lPreviewHandle,savePath))){
            logger.info("录制启动错误代码：{}",hCNetSDK.NET_DVR_GetLastError());
            return false;
        }
        try {
            Thread.sleep(saveTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //此处等待5s
        if(!hCNetSDK.NET_DVR_StopSaveRealData(lPreviewHandle)){
            logger.info("录制关闭错误代码：{}",hCNetSDK.NET_DVR_GetLastError());
            return false;
        }
        logger.info("录制完成，路径为：{}",savePath);
        try {
            File file=new File(savePath);
            FileInputStream fileInputStream=new FileInputStream(file);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        //todo 录制完成之后，上传文件，然后将该条数据保存到表里
        //this.bRfidWarns 
        return true;
    }

    @Override
    public boolean hcNetClean() {
        //如果在预览,先停止预览, 释放句柄
        if (!ObjectUtils.isEmpty(lPreviewHandle1) &&lPreviewHandle1.longValue() > -1) {
            hCNetSDK.NET_DVR_StopRealPlay(lPreviewHandle1);//停止预览
        }
        //如果已经注册,注销
        if (!ObjectUtils.isEmpty(lUserID1) && lUserID1.longValue() > -1)
        {
            hCNetSDK.NET_DVR_Logout_V30(lUserID1);
        }
        //如果在预览,先停止预览, 释放句柄
        if (!ObjectUtils.isEmpty(lPreviewHandle2) &&lPreviewHandle2.longValue() > -1) {
            hCNetSDK.NET_DVR_StopRealPlay(lPreviewHandle2);//停止预览
        }
        //如果已经注册,注销
        if (!ObjectUtils.isEmpty(lUserID2) && lUserID2.longValue() > -1)
        {
            hCNetSDK.NET_DVR_Logout_V30(lUserID2);
        }
        return false;
    }



}
